from flask import Blueprint, render_template, jsonify, request, make_response
from app import db
from app.models import Question, Config, DrawRecord
import random
import uuid
import json
from datetime import datetime, timedelta
from sqlalchemy import and_

bp = Blueprint('main', __name__)

def get_user_token():
    token = request.cookies.get('user_token')
    if not token:
        token = str(uuid.uuid4())
        # 创建一个响应对象
        response = make_response()
        # 设置cookie，有效期30天
        response.set_cookie('user_token', token, max_age=30*24*60*60)
        return token, response
    return token, None

def get_config(key, default=None):
    config = Config.query.filter_by(key=key).first()
    if config:
        try:
            return int(config.value)
        except (ValueError, TypeError):
            return default
    return default

def get_questions(count):
    questions = Question.query.all()
    if len(questions) < count:
        count = len(questions)
    return random.sample(questions, count)

def get_client_ip():
    # 尝试从X-Forwarded-For获取真实IP
    if request.headers.get('X-Forwarded-For'):
        return request.headers.get('X-Forwarded-For').split(',')[0].strip()
    # 尝试从X-Real-IP获取真实IP
    if request.headers.get('X-Real-IP'):
        return request.headers.get('X-Real-IP')
    # 如果都没有，返回remote_addr
    return request.remote_addr

def check_draw_limit(token, ip, user_agent):
    # 检查最近1小时内的抽题限制
    one_hour_ago = datetime.utcnow() - timedelta(hours=1)
    
    # 检查同一用户（token）在最近1小时内的抽题次数
    user_draws = DrawRecord.query.filter(
        and_(
            DrawRecord.user_token == token,
            DrawRecord.draw_time > one_hour_ago
        )
    ).count()
    
    # 检查同一IP在最近1小时内的抽题次数
    ip_draws = DrawRecord.query.filter(
        and_(
            DrawRecord.ip_address == ip,
            DrawRecord.draw_time > one_hour_ago
        )
    ).count()
    
    # 检查同一IP和User-Agent组合在最近1小时内的抽题次数
    ip_ua_draws = DrawRecord.query.filter(
        and_(
            DrawRecord.ip_address == ip,
            DrawRecord.user_agent == user_agent,
            DrawRecord.draw_time > one_hour_ago
        )
    ).count()
    
    # 如果用户token、IP或IP+UA组合在1小时内抽题超过限制，返回False
    return user_draws < 3 and ip_draws < 5 and ip_ua_draws < 3

@bp.route('/')
def index():
    # Get all configs
    configs = {}
    for config in Config.query.all():
        try:
            # 尝试将值转换为整数
            configs[config.key] = int(config.value)
        except (ValueError, TypeError):
            # 如果转换失败，保持原值
            configs[config.key] = config.value
    
    return render_template('main/index.html', configs=configs)

@bp.route('/draw', methods=['POST'])
def draw():
    try:
        # 获取学号
        student_id = request.form.get('student_id')
        if not student_id:
            return jsonify({'success': False, 'message': '请输入学号'})
            
        # 获取用户信息
        user_token, token_response = get_user_token()
        ip_address = get_client_ip()
        user_agent = request.user_agent.string[:255]  # 截断到255个字符

        print(f"Draw attempt - Student ID: {student_id}, IP: {ip_address}, User Agent: {user_agent}")

        # 检查抽题限制
        if not check_draw_limit(user_token, ip_address, user_agent):
            print(f"Draw limit exceeded - Token: {user_token}, IP: {ip_address}")
            return jsonify({'success': False, 'message': '抽题过于频繁，请稍后再试'})

        # 获取可用题目
        available_questions = Question.query.all()
        if not available_questions:
            print("No available questions found")
            return jsonify({'success': False, 'message': '暂无可用题目'})

        print(f"Found {len(available_questions)} available questions")

        # 获取每次抽题数量
        questions_per_draw = get_config('questions_per_draw', 1)
        if len(available_questions) < questions_per_draw:
            questions_per_draw = len(available_questions)
            print(f"Adjusted questions_per_draw to {questions_per_draw}")

        # 随机选择题目
        selected_questions = random.sample(available_questions, questions_per_draw)
        print(f"Selected {len(selected_questions)} questions")

        # 记录抽题记录（只创建一条记录）
        record = DrawRecord(
            student_id=student_id,
            user_token=user_token,
            ip_address=ip_address,
            user_agent=user_agent,
            is_redraw=False
        )
        record.set_question_ids([q.id for q in selected_questions])
        db.session.add(record)
        db.session.commit()
        print(f"Successfully created draw record with ID: {record.id}")

        # 创建响应
        response_data = {
            'success': True,
            'data': {
                'questions': [{
                    'id': q.id,
                    'content': q.content
                } for q in selected_questions]
            }
        }
        
        # 如果有token_response，使用它
        if token_response:
            response = jsonify(response_data)
            response.set_cookie('user_token', user_token, max_age=30*24*60*60)
            return response
        
        return jsonify(response_data)
    except Exception as e:
        print(f"Error in draw route: {str(e)}")
        print(f"Error type: {type(e)}")
        print(f"Error args: {e.args}")
        db.session.rollback()
        return jsonify({'success': False, 'message': '抽题失败，请稍后重试'})

@bp.route('/redraw')
def redraw():
    token, token_response = get_user_token()
    ip = get_client_ip()
    
    # 检查抽题限制
    if not check_draw_limit(token, ip, request.user_agent.string):
        return jsonify({'error': '抽题过于频繁，请稍后再试'}), 429
    
    # Check redraw limit
    redraw_limit = get_config('retry_limit', 0)
    current_redraws = DrawRecord.query.filter_by(
        user_token=token,
        is_redraw=True
    ).count()
    
    if current_redraws >= redraw_limit:
        return jsonify({'error': '重抽次数已用完'}), 403
    
    # 直接查询最近的一条非重抽记录
    original_record = DrawRecord.query.filter_by(
        user_token=token,
        is_redraw=False
    ).order_by(DrawRecord.draw_time.desc()).first()
    
    # 添加调试信息
    print(f"Token: {token}")
    print(f"Original record: {original_record}")
    if original_record:
        print(f"Student ID: {original_record.student_id}")
        print(f"Draw time: {original_record.draw_time}")
        print(f"Is redraw: {original_record.is_redraw}")
    
    if not original_record:
        # 尝试查找任何记录，看看是否有问题
        any_record = DrawRecord.query.filter_by(user_token=token).first()
        if any_record:
            print(f"Found any record: {any_record.id}, is_redraw: {any_record.is_redraw}")
        else:
            print("No records found at all")
        return jsonify({'error': '未找到原始抽题记录，请先进行抽题'}), 400
    
    # Get all previously drawn questions
    previous_records = DrawRecord.query.filter_by(user_token=token).all()
    previous_question_ids = set()
    for record in previous_records:
        previous_question_ids.update(record.get_question_ids())
    
    # Get new questions
    questions_per_draw = get_config('questions_per_draw', 1)
    available_questions = Question.query.filter(
        Question.id.notin_(previous_question_ids)
    ).all()
    
    if len(available_questions) < questions_per_draw:
        return jsonify({'error': '没有更多可用题目'}), 400
    
    new_questions = random.sample(available_questions, questions_per_draw)
    
    # 创建重抽记录
    record = DrawRecord(
        user_token=token,
        student_id=original_record.student_id,  # 使用原始抽题的学号
        ip_address=ip,
        user_agent=request.user_agent.string[:255],  # 截断到255个字符
        is_redraw=True
    )
    record.set_question_ids([q.id for q in new_questions])
    db.session.add(record)
    db.session.commit()
    
    # 创建响应
    response_data = {
        'questions': [{'id': q.id, 'content': q.content} for q in new_questions],
        'remaining_redraws': redraw_limit - (current_redraws + 1)
    }
    
    # 如果有token_response，使用它
    if token_response:
        response = jsonify(response_data)
        response.set_cookie('user_token', token, max_age=30*24*60*60)
        return response
    
    return jsonify(response_data) 